using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using System.Configuration.Provider;
using System.Security.Permissions;
using System.Web;
using System.Web.Configuration;
using System.Web.Security;
using System.Web.UI;
using System.Web.Caching;

namespace XZ.Content.Mailings
{
    [SqlClientPermission(SecurityAction.Demand, Unrestricted = true)]
    public class SqlMailingProvider : MailingProvider
    {
        private string _applicationName;
        private string _connectionString;

        public override string ApplicationName
        {
            get { return _applicationName; }
            set { _applicationName = value; }
        }

        public string ConnectionString//Name
        {
            get { return _connectionString; }
            set { _connectionString = value; }
        }

        public override void Initialize(string name, NameValueCollection config)
        {
            // Verify that config isn't null
            if (config == null)
                throw new ArgumentNullException("config");

            // Assign the provider a default name if it doesn't have one
            if (String.IsNullOrEmpty(name))
                name = "SqlNewsletterProvider";

            // Add a default "description" attribute to config if the
            // attribute doesn't exist or is empty
            if (string.IsNullOrEmpty(config["description"]))
            {
                config.Remove("description");
                config.Add("description", "SQL Mailing provider");
            }

            // Call the base class's Initialize method
            base.Initialize(name, config);

            // Initialize _applicationName
            _applicationName = config["applicationName"];

            if (string.IsNullOrEmpty(_applicationName))
                _applicationName = "/";

            config.Remove("applicationName");

            // Initialize _connectionString
            string connect = config["connectionStringName"];

            if (String.IsNullOrEmpty(connect))
                throw new ProviderException("Empty or missing connectionStringName");

            config.Remove("connectionStringName");

            if (WebConfigurationManager.ConnectionStrings[connect] == null)
                throw new ProviderException("Missing connection string");

            _connectionString = WebConfigurationManager.ConnectionStrings[connect].ConnectionString;

            if (String.IsNullOrEmpty(_connectionString))
                throw new ProviderException("Empty connection string");

            // Throw an exception if unrecognized attributes remain
            if (config.Count > 0)
            {
                string attr = config.GetKey(0);
                if (!String.IsNullOrEmpty(attr))
                    throw new ProviderException("Unrecognized attribute: " + attr);
            }
        }
        /// <summary>
        /// Returns a collection with all the Mailings sent before the specified date
        /// </summary>
        public override List<Mailing> GetMailings(DateTime toDate)
        {
            using (SqlConnection cn = new SqlConnection(this.ConnectionString))
            {
                SqlCommand cmd = new SqlCommand("xz_Mailings_GetMailings", cn);
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.Parameters.Add("@ApplicationName", SqlDbType.NVarChar).Value = ApplicationName;
                cmd.Parameters.Add("@ToDate", SqlDbType.DateTime).Value = toDate;
                cn.Open();
                return GetMailingCollectionFromReader(ExecuteReader(cmd), false);
            }
        }

        /// <summary>
        /// Returns an existing Mailing with the specified ID
        /// </summary>
        public override Mailing GetMailingByID(Guid mailingID)
        {
            using (SqlConnection cn = new SqlConnection(this.ConnectionString))
            {
                SqlCommand cmd = new SqlCommand("xz_Mailings_GetMailingByID", cn);
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.Parameters.Add("@ApplicationName", SqlDbType.NVarChar).Value = ApplicationName;
                cmd.Parameters.Add("@MailingId", SqlDbType.UniqueIdentifier).Value = mailingID;
                cn.Open();
                IDataReader reader = ExecuteReader(cmd, CommandBehavior.SingleRow);
                if (reader.Read())
                    return GetMailingFromReader(reader);
                else
                    return null;
            }
        }

        /// <summary>
        /// Deletes a Mailing
        /// </summary>
        public override bool DeleteMailing(Guid mailingID)
        {
            using (SqlConnection cn = new SqlConnection(this.ConnectionString))
            {
                SqlCommand cmd = new SqlCommand("xz_Mailings_DeleteMailing", cn);
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.Parameters.Add("@ApplicationName", SqlDbType.NVarChar).Value = ApplicationName;
                cmd.Parameters.Add("@MailingId", SqlDbType.UniqueIdentifier).Value = mailingID;
                cn.Open();
                int ret = ExecuteNonQuery(cmd);
                return (ret == 1);
            }
        }

        /// <summary>
        /// Updates a Mailing
        /// </summary>
        public override bool UpdateMailing(Mailing mailing)
        {
            using (SqlConnection cn = new SqlConnection(this.ConnectionString))
            {
                SqlCommand cmd = new SqlCommand("xz_Mailings_UpdateMailing", cn);
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.Parameters.Add("@ApplicationName", SqlDbType.NVarChar).Value = ApplicationName;
                cmd.Parameters.Add("@MailingId", SqlDbType.UniqueIdentifier).Value = mailing.ID;
                cmd.Parameters.Add("@Subject", SqlDbType.NVarChar).Value = mailing.Subject;
                cmd.Parameters.Add("@PlainTextBody", SqlDbType.NText).Value = mailing.PlainTextBody;
                cmd.Parameters.Add("@HtmlBody", SqlDbType.NText).Value = mailing.HtmlBody;
                cn.Open();
                int ret = ExecuteNonQuery(cmd);
                return (ret == 1);
            }
        }

        /// <summary>
        /// Creates a new Mailing
        /// </summary>
        public override Guid InsertMailing(Mailing mailing)
        {
            using (SqlConnection cn = new SqlConnection(this.ConnectionString))
            {
                SqlCommand cmd = new SqlCommand("xz_Mailings_InsertMailing", cn);
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.Parameters.Add("@ApplicationName", SqlDbType.NVarChar).Value = ApplicationName;
                cmd.Parameters.Add("@AddedDate", SqlDbType.DateTime).Value = mailing.AddedDate;
                cmd.Parameters.Add("@AddedBy", SqlDbType.NVarChar).Value = mailing.AddedBy;
                cmd.Parameters.Add("@Subject", SqlDbType.NVarChar).Value = mailing.Subject;
                cmd.Parameters.Add("@PlainTextBody", SqlDbType.NText).Value = mailing.PlainTextBody;
                cmd.Parameters.Add("@HtmlBody", SqlDbType.NText).Value = mailing.HtmlBody;
                cmd.Parameters.Add("@MailingId", SqlDbType.UniqueIdentifier).Direction = ParameterDirection.Output;
                cn.Open();
                int ret = ExecuteNonQuery(cmd);
                return (Guid)cmd.Parameters["@MailingID"].Value;
            }
        }
    }
}